<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Identifier subtypes</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.10">
<link rel="up" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.10">
<link rel="prev" href="vmd_modifiers/vmd_modifiers_single.html" title="Modifiers and the single-element sequence">
<link rel="next" href="vmd_useful.html" title="Useful variadic macros not in Boost PP">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="variadic_macro_data.vmd_identifier_subtype"></a><a class="link" href="vmd_identifier_subtype.html" title="Identifier subtypes">Identifier
    subtypes</a>
</h2></div></div></div>
<p>
      Identifiers are the low-level data types which macro programmers use to pass
      preprocessing data most often. As we have seen VMD has a system for registering
      and detecting identifiers so that they can be parsed as part of preprocessor
      data. This system also includes comparing identifiers for equality or inequality
      using BOOST_VMD_EQUAL/BOOST_VMD_NOT_EQUAL and matching identifiers using identifier
      modifiers in BOOST_VMD_IS_IDENTIFIER and BOOST_VMD_ELEM. Together these facilities
      provide a rich set of functionality for handling identifiers in macros.
    </p>
<p>
      Both numbers and v-types are subtypes of identifiers, and can both be individually
      recognized as data types of their own or worked with as identifiers using the
      identifier facilities already mentioned. Numbers, in particular, also have
      a rich set of functionality within the Boost PP library. As subtypes numbers
      and v-types can be used as filter modifiers and can be returned as specific
      types either when invoking BOOST_VMD_GET_TYPE or when using return type modifiers.
      Furthermore VMD recognizes their individual v-types, BOOST_VMD_TYPE_NUMBER
      and BOOST_VMD_TYPE_TYPE, as VMD data when parsing sequences.
    </p>
<p>
      It is possible for the end-user to define his own identifier subtype. This
      is called a "user-defined subtype". Once a user-define subtype is
      created all the generic type facilities of VMD which subtypes such as a number
      or a v-type possess is automatically available for that user-defined subtype.
    </p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h0"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.defining_a_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.defining_a_subtype">Defining
      a subtype</a>
    </h4>
<p>
      In order to define a user-defined subtype a number of steps need to be followed.
      These steps will be explained in detail further below:
    </p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
          Register and pre-detect all identifiers of that subtype.
        </li>
<li class="listitem">
          Register and pre-detect a v-type name for that subtype.
        </li>
<li class="listitem">
          Subset register all identifiers of the subtype.
        </li>
<li class="listitem">
          Subset register the v-type name for the subtype.
        </li>
</ol></div>
<p>
      When we do the above, it is best to put all the macros in a single header file
      and always include that header file when we work generically with our user-defined
      subtype.
    </p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h1"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden">Register
      and pre-detect all identifiers of that subtype</a>
    </h4>
<p>
      Registering and pre-detecting all of the identifiers of that subtype is exactly
      the same as registering and pre-detecting any identifier.
    </p>
<p>
      Let's create some identifiers based for use in the mythical "udef"
      library. We will put all our macros in the header file udef_vmd_macros.hpp.
    </p>
<p>
      We will need distinct names for the identifiers in our library, so we will
      append UDEF_ to our identifier names to make them unique. Our udef library
      deals in geometrical shapes so we will create a user-defined subtype which
      consists of identifiers for the various shapes our udef library can manipulate
      in their macros. So our identifier registrations and pre-detections placed
      in our header file will be:
    </p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>

<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_CIRCLE_UDEF_CIRCLE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_SQUARE_UDEF_SQUARE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_TRIANGLE_UDEF_TRIANGLE</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_HEXAGON_UDEF_HEXAGON</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h2"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type">Register
      and pre-detect a v-type name for that subtype</a>
    </h4>
<p>
      We need to create a unique v-type name for our user-defined subtype. The name
      does not have to begin with BOOST_VMD_TYPE_ but it should be unique. Since
      BOOST_VMD_TYPE_ is the common beginning of all v-types we will use it for consistency
      but will append to it UDEF_SHAPES to give it a uniqueness which should not
      be duplicated:
    </p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>

<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_BOOST_VMD_TYPE_UDEF_SHAPES_BOOST_VMD_TYPE_UDEF_SHAPES</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h3"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers">Subtype
      register all identifiers of the subtype</a>
    </h4>
<p>
      The macro to register an identifier subset starts with BOOST_VMD_SUBTYPE_REGISTER_
      and you append to it each identifier in the subset. This is very much like
      the way you use the BOOST_VMD_REGISTER_ macro. The difference is that unlike
      the BOOST_VMD_REGISTER_ macro, which expands to a tuple whose single element
      is the identifier, the BOOST_VMD_SUBTYPE_REGISTER_ expands to a tuple of two
      elements where the first element is the subtype v-type and the second element
      is the identifier.
    </p>
<p>
      For our udef user-defined subtype this would be:
    </p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h4"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name">Subtype
      register the v-type name for the subtype</a>
    </h4>
<p>
      Doing a subset register of the actual udef v-type is fairly easy once we understand
      how to register an identifier subset. The only particular thing to realize
      is that the type of any v-type is the v-type BOOST_VMD_TYPE_TYPE. So our subset
      register of our new v-type BOOST_VMD_TYPE_UDEF_SHAPES is:
    </p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>
</pre>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h5"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset">Using
      our identifier subset</a>
    </h4>
<p>
      Once we have added all of the above object-like macros for defining our user-defined
      subtype to the udef_vmd_macros.hpp header file we have a new data type which
      we can use generically just like we can use numbers or v-types generically.
      It is important to include the header udef_vmd_macros.hpp in some translation
      unit whenever we need the VMD functionality for our new data type. So in our
      examples we will assume that an '#include udef_vmd_macros.hpp' precedes each
      example.
    </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="identifier">UDEF_SQUARE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE2</span> <span class="number">217</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE3</span> <span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE4</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span>

<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_UDEF_SHAPES'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_NUMBER'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
<span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE4</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
</pre>
<p>
      Here we see that when we use our BOOST_VMD_GET_TYPE macro on a single-element
      sequence which is one of our user-defined subtype values we correctly get back
      our user-defined subtype's v-type, just like we do when we ask for the type
      of a number. Also when we use our BOOST_VMD_GET_TYPE macro on our user-defined
      subtype's v-type itself we correctly get back the type of all v-types, which
      is BOOST_VMD_TYPE_TYPE, just like we do when we ask for the type of the v-type
      of a number.
    </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE5</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span> <span class="identifier">UDEF_TRIANGLE</span>

<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_UDEF_SHAPES,UDEF_TRIANGLE)'</span>
<span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(1,2))'</span>
</pre>
<p>
      Here we see that we can use the return type modifier to get back both the type
      and the value in a two-element tuple for our user-defined subtype just as we
      so for any other type.
    </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE6</span> <span class="identifier">UDEF_CIRCLE</span>
<span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE7</span> <span class="number">168</span>

<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
<span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
</pre>
<p>
      Here we can see that we can use the filter modifier with our user-defined subtype's
      v-type just as we can do with any other v-type, such as the number v-type.
    </p>
<p>
      In all respects once we define our subtype and provide those definitions in
      a header file, our user-defined subtype acts like any other v-type in our system.
      Since VMD functionality is largely based on being able to recognize the type
      of data in macro input being able to define another 'type', as an identifier
      subtype, which VMD understands has value for the macro programmer.
    </p>
<h4>
<a name="variadic_macro_data.vmd_identifier_subtype.h6"></a>
      <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype">Uniqueness
      of identifier subtype values and v-type</a>
    </h4>
<p>
      When we define a new identifier subtype we need to be careful that the values
      of that subtype and its actual v-type are unique identifiers within any translation
      unit. This is the main difference between just defining identifiers and defining
      an identifier subtype.
    </p>
<p>
      Recall that when we just register and pre-detect identifiers we will have no
      problems if the same identifiers already have been registered and pre-detected
      within the same translation unit. This is because we are just redefining the
      exact same macro if this is the case.
    </p>
<p>
      But with identifier subtypes, when we use the BOOST_VMD_SUBTYPE_REGISTER_ macro
      to associate our subtype's v-type with our subtype identifiers, we will have
      problems if someone else has also defined an identifier subtype using the same
      identifiers as we use since we will be redefining the same object-like macro
      name with a different expansion. Even if someone else has registered/pre-detected
      an identifier we are using for out subtype without defining a subtype based
      on that identifier we will be causing a problem defining our subtype because
      VMD macros which generically return the type of a sequence or sequence element
      will return our subtype as the type rather than just BOOST_VMD_TYPE_IDENTIFIER
      which some programmer might expect.
    </p>
<p>
      The gist of this is that if we define a user-defined subtype its identifiers
      need to be unique within a given translation unit, and yet unique names make
      it harder for an end-user to use macros more naturally. In our given example
      with the mythical udef library we used identifiers such as 'UDEF_CIRCLE' etc.
      instead of the more natural sounding CIRCLE. So with user-defined identifier
      subtypes we have a tradeoff; we need unique identifier names both for our subtype
      identifiers and the v-type for our subtype identifiers so as not to conflict
      with others who might be using identifier subtypes, but those unique names
      might make using macros less "natural" On the other hand, just registering/pre-detecting
      identifiers has no such problem. This is an issue of which any user, looking
      to create his own data type using VMD by defining user-defined subtypes, should
      be aware.
    </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2010-2017 Tropic Software
      East Inc</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
